/**
 * Fuzzy Refrigerator: Refrigerator with Fuzzy Logic as temperature controller
 * Copyright (C) 2012  Izwan Azmi
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

 /**
  * @file fuzzy.cpp
  * @brief Bahagian implementasi bagi semua fungsi fuzzy
  * @author Izwan Azmi <izwanazmi90@gmail.com>
  */

#include "fuzzy.h"

fuzzy::fuzzy() {
    //ctor
}

fuzzy::~fuzzy() {
    //dtor
}

trapezoid fuzzy::init_trapz(float x1, float x2, float x3, float x4, jenis_trapz jenis) {
    trapezoid trz;
    trz.a  = x1;
    trz.b  = x2;
    trz.c  = x3;
    trz.d  = x4;
    trz.jt = jenis;

    switch (trz.jt) {
    case biasa:
        trz.cerun_kiri = 1.0/(trz.b-trz.a);
        trz.cerun_kanan = 1.0/(trz.c-trz.d);
        break;
    case kiri:
        trz.cerun_kanan = 1.0/(trz.a-trz.b);
        trz.cerun_kiri = 0.0;
        break;
    case kanan:
        trz.cerun_kiri = 1.0/(trz.b-trz.a);
        trz.cerun_kanan = 0.0;
        break;
    }

    return trz;
}

float fuzzy::fuzzification(float x, trapezoid trz) {
    switch (trz.jt) {
    case kiri:
        if (x <= trz.a)
            return 1.0;
        if (x >= trz.b)
            return 0.0;
        /* a < x < b */
        return trz.cerun_kanan * (x-trz.b);

    case kanan:
        if (x <= trz.a)
            return 0.0;
        if (x >= trz.b)
            return 1.0;
        /* a < x < b */
        return trz.cerun_kiri * (x-trz.a);

    case biasa:
        if ((x <= trz.a) || (x >= trz.d))
            return 0.0;
        if ((x >= trz.b) && (x <= trz.c))
            return 1.0;
        if ((x >= trz.a) && (x <= trz.b))
            return trz.cerun_kiri * (x - trz.a);
        if ((x >= trz.c) && (x <= trz.d))
            return trz.cerun_kanan * (x - trz.d);
    }
    return 0.0; // should not get to this point
}

float fuzzy::getMin(float data[], int saiz) {
    double val;
    val = data[0];

    for (int i = 1; i < saiz; i++) {
        if (data[i] < val)
            val = data[i];
    }

    return val;
}

float fuzzy::getMax(float data[], int saiz) {
    double val;
    val = data[0];

    for (int i = 1; i < saiz; i++) {
        if (data[i] > val)
            val = data[i];
    }

    return val;
}
